package com.ruyuan.rapid.core.netty.processor.filter;

import com.ruyuan.rapid.common.util.ServiceLoader;
import com.ruyuan.rapid.core.context.Context;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

/**
 * 默认过滤器工厂实现类
 * @author mac
 */
@Slf4j
public class DefaultProcessorFilterFactory extends AbstractProcessorFilterFactory {

    private static class SingletonHolder {
        private static final DefaultProcessorFilterFactory INSTANCE = new DefaultProcessorFilterFactory();
    }

    /**
     * 构造方法: 加载所有的ProcessorFilter子类的实现
     */
    @SuppressWarnings("all")
    private DefaultProcessorFilterFactory() {
        // SPI方式加载filter的容器集合
        Map<String, List<ProcessorFilter<Context>>> filterMap = new LinkedHashMap<>();
        // 通过ServiceLoader加载
        ServiceLoader<ProcessorFilter> serviceLoader = ServiceLoader.load(ProcessorFilter.class);
        for (ProcessorFilter filter : serviceLoader) {
            Filter annotation = filter.getClass().getAnnotation(Filter.class);
            if (annotation != null) {
                String filterType = annotation.value().getCode();
                List<ProcessorFilter<Context>> filterList = filterMap.get(filterType);
                if (filterList == null) {
                    filterList = new ArrayList<>();
                }
                filterList.add(filter);
                filterMap.put(filterType, filterList);
            }
        }

        for (ProcessorFilterType filterType : ProcessorFilterType.values()) {
            List<ProcessorFilter<Context>> filterList = filterMap.get(filterType.getCode());
            if (filterList == null || filterList.isEmpty()) {
                continue;
            }
            Collections.sort(filterList, new Comparator<ProcessorFilter<Context>>() {
                @Override
                public int compare(ProcessorFilter<Context> o1, ProcessorFilter<Context> o2) {
                    Filter annotation1 = o1.getClass().getAnnotation(Filter.class);
                    Filter annotation2 = o2.getClass().getAnnotation(Filter.class);
                    return annotation1.order() - annotation2.order();
                }
            });

            try {
                super.buildFilterChain(filterType, filterList);
            } catch (Exception e) {
                log.error("DefaultProcessorFilterFactory.buildFiterChain 网关过滤器加载异常, 异常信息为: {} !", e.getMessage(), e);
            }
        }
    }

    public static DefaultProcessorFilterFactory getInstance() {
        return SingletonHolder.INSTANCE;
    }

    /**
     * 正常情况下执行的过滤器链: pre+route+post
     * @param ctx
     * @throws Exception
     */
    @Override
    public void doFilterChain(Context ctx) throws Exception {
        try {
            defaultProcessorFilterChain.entry(ctx);
        } catch (Throwable e) {
            log.error("DefaultProcessorFilterFactory doFilterChain exception: {}", e.getMessage(), e);

            // 设置异常
            ctx.setThrowable(e);

            // 执行doFilterChain抛出异常时, Context上下文的生命周期为Terminated
            if (ctx.isTerminated()) {
                // 恢复上下文生命周期为Running
                ctx.runned();
            }

            // 异常时需要执行异常处理过滤器链
            doErrorFilterChain(ctx);
        }
    }

    /**
     * 异常情况下执行该过滤器链: error+post
     * @param ctx
     * @throws Exception
     */
    @Override
    public void doErrorFilterChain(Context ctx) throws Exception {
        try {
            errorProcessorFilterChain.entry(ctx);
        } catch (Throwable e) {
            log.error("DefaultProcessorFilterFactory doErrorFilterChain exception: {}", e.getMessage(), e);
        }
    }
}
